#include "Prerequisites.h"
#include "Geometry.h"

//========================================================================
// 
// Note - FVFs are part of the fixed function pipeline, and were described in
//        Game Coding Complete, 3rd Edition. 
//
// Our custom FVF, which describes our custom vertex structure
// These were #define'd in the book - now they are static constants.
//

const DWORD D3D9Vertex_UnlitColored::FVF =
	(D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DFVF_SPECULAR);		
const DWORD D3D9Vertex_ColoredTextured::FVF = (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1);
const DWORD D3D9Vertex_Colored::FVF = (D3DFVF_XYZ|D3DFVF_DIFFUSE);
const DWORD D3D9Vertex_UnlitTextured::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;


Vector3 BarycentricToVector3(Vector3 v0, Vector3 v1, Vector3 v2, float u, float v)
{
	//V1 + U(V2 - V1) + V(V3 - V1).
	Vector3 result = v0 + u * (v1  - v0) + v * (v2 - v0);
	return result;
}


//--------------------------------------------------------------------------------------
// Given a ray origin (orig) and direction (dir), and three vertices of a triangle, this
// function returns TRUE and the interpolated texture coordinates if the ray intersects 
// the triangle
//--------------------------------------------------------------------------------------
bool IntersectTriangle( const Vector3& orig, const Vector3& dir,
                        Vector3& v0, Vector3& v1, Vector3& v2,
                        FLOAT* t, FLOAT* u, FLOAT* v )
{
    // Find vectors for two edges sharing vert0
    Vector3 edge1 = v1 - v0;
    Vector3 edge2 = v2 - v0;

    // Begin calculating determinant - also used to calculate U parameter
    Vector3 pvec;
    D3DXVec3Cross( &pvec, &dir, &edge2 );

    // If determinant is near zero, ray lies in plane of triangle
    FLOAT det = D3DXVec3Dot( &edge1, &pvec );

    Vector3 tvec;
    if( det > 0 )
    {
        tvec = orig - v0;
    }
    else
    {
        tvec = v0 - orig;
        det = -det;
    }

    if( det < 0.0001f )
        return FALSE;

    // Calculate U parameter and test bounds
    *u = D3DXVec3Dot( &tvec, &pvec );
    if( *u < 0.0f || *u > det )
        return FALSE;

    // Prepare to test V parameter
    Vector3 qvec;
    D3DXVec3Cross( &qvec, &tvec, &edge1 );

    // Calculate V parameter and test bounds
    *v = D3DXVec3Dot( &dir, &qvec );
    if( *v < 0.0f || *u + *v > det )
        return FALSE;

    // Calculate t, scale parameters, ray intersects triangle
    *t = D3DXVec3Dot( &edge2, &qvec );
    FLOAT fInvDet = 1.0f / det;
    *t *= fInvDet;
    *u *= fInvDet;
    *v *= fInvDet;

    return TRUE;
}



bool TriangleIterator::InitializeStrippedMesh(LPDIRECT3DVERTEXBUFFER9 pVerts, int stride, int strips, int *triCountList )
{
	char *pVertices = NULL;
	if( FAILED( pVerts->Lock( 0, 0, (void**)&pVertices, 0 ) ) )
        return false;

	for (int i=0; i<strips; ++i)
	{
		m_Size += triCountList[i];
	}

	m_Triangles = NEW Vector3[m_Size * 3];
	int src = 0;
	int dest = 0;

	for (int strip=0; strip<strips; ++strip )
	{
		int vertsInStrip = triCountList[strip]+2;
		ASSERT(vertsInStrip);

		m_Triangles[dest] = *((Vector3*)&pVertices[stride * src]);
		m_Triangles[dest+1] = *((Vector3*)&pVertices[stride * (src+1)]);
		m_Triangles[dest+2] = *((Vector3*)&pVertices[stride * (src+2)]);
		dest+=3;
		src+=3;
		for (int tri=1; tri<triCountList[strip]; ++tri)
		{
			// for every extra vertex in the triangle strip, you have to grab
			// the two previous verts in the dest list, reverse them, and copy them
			// forward. This will give you a triangle with the same winding
			m_Triangles[dest] = m_Triangles[dest-1];
			m_Triangles[dest+1] = m_Triangles[dest-2];
			m_Triangles[dest+2] = *((Vector3*)&pVertices[stride * (++src)]);
			dest+=3;
		}
	}
	ASSERT(dest==m_Size*3);
	pVerts->Unlock();

	return true;
}

void *TriangleIterator::VGet(unsigned int i) 
{	
	ASSERT(i<m_Size);
	return &m_Triangles[i*3]; 
}